import org.jlinalg.LinSysSolver;
import org.jlinalg.Matrix;
import org.jlinalg.Rational;
import org.jlinalg.FieldElement;
import org.jlinalg.Vector;

import java.util.*;
import java.io.*;
import java.math.BigInteger;

/**
 * Example that computes a solution of a linear equation system for the domain
 * of rational numbers.
 * 
 * @author Andreas Keilhauer, Georg Thimm
 */
public class CheckVertices
{
        public static boolean DEBUG = false;

	/**
	 * start the demonstration
	 * 
	 * @param argv
	 *            is ignored
	 */
	public static void main(String[] argv)
	{
	String fileName = argv[0];
	String rows = argv[1];
	String cols = argv[2];
	String verName = argv[3];

	if( argv.length > 4 )
		{
		if( argv[4].equals("DEBUG") )
			{
			DEBUG = true;
			}
		}
	
	int r = Integer.parseInt(rows);
	int c = Integer.parseInt(cols);

	System.out.println("* Will assume that file '"+fileName+"' contains "+r+" rows and "+c+" columns (with no header data!) and that 'vertex' data is in file "+verName+".");
	System.out.println("* Will assume that the matrix is of the form a0 a1 a2... and becomes a1 + a2 + ... >= -a0");
	System.out.println("* Will assume that the vertices have "+(c-1)+" co-ordinates!");

	Rational[][] nums = new Rational[r][c];

	Rational[][] adata = new Rational[r][c-1];

	Rational[] bdata = new Rational[r];
	
	int at = 0;

                        try     {
                                FileReader fr = new FileReader(fileName);
                                BufferedReader br = new BufferedReader(fr);

                                String record = new String();
                                while((record=br.readLine()) != null)
                                        {
                                        if( record.startsWith("//") ) continue; //! ignore comments

                                        String[] tripData = record.split(" ");

					for( int x=0; x<c; x++ )
						{
						String numerator = null;
						String denominator = null;

						String ratString = tripData[x];

						int locbar = ratString.indexOf('/');
						if( locbar == -1 )
							{
							numerator = ratString;
							denominator = "1";
							}
						else
							{
							numerator = ratString.substring( 0, locbar );
							denominator = ratString.substring( locbar+1 );
							}

						// System.out.println("* Got rational ["+numerator+"]["+denominator+"]");

						BigInteger bnum = new BigInteger(numerator);
						BigInteger dnum = new BigInteger(denominator);

						nums[at][x] = new Rational(bnum, dnum);

						if( x>0 )
							{
							adata[at][x-1] = new Rational(bnum,dnum);
							}
						else
							{
							bdata[at] = new Rational(bnum, dnum);
							bdata[at] = bdata[at].negate();
							}
						
						// System.out.print(" "+nums[at][x]+" ");

						}
					at++;
					// System.out.println();
					}

                                }
                        catch (IOException e)
                                {
                                // catch possible io errors from readLine()
                                System.out.println("Problem reading file "+fileName);
                                System.exit(0);
                                }

	System.out.println("* Will now strip out the 'A' part of the Ax >= b data...");

		if(DEBUG)
		{
		for(int x=0; x<adata.length; x++)
		{
		if(DEBUG) System.out.print("* ");

		for(int y=0; y<adata[x].length; y++ )
			{
			if(DEBUG) System.out.print(adata[x][y].toString()+" ");
			}
		if(DEBUG) System.out.println();
		}
		}

                Matrix<Rational> a = new Matrix<Rational>(adata);

                 System.out.println("* Formal matrix object 'A' has "+a.getRows()+" rows and "+a.getCols()+" columns.");

	System.out.println("* And now the 'b' vector...");

		if(DEBUG)
		{
		for(int x=0; x<adata.length; x++)
		{
		if(DEBUG) System.out.println("* "+bdata[x]);
		}
		}
	
	Vector<Rational> bvec = new Vector<Rational>(bdata);

		int verSeen = 0;

	//! I added this to stop it doing more than 10 vertices...
	int done=0;

	System.out.println("* Ok, I have read in the .ine file. Will now read in the 'vertices' and check them one at at a time...");

                        try     {
                                FileReader fr = new FileReader(verName);
                                BufferedReader br = new BufferedReader(fr);

                                String record = new String();
                                verloop: while((record=br.readLine()) != null)
                                        {
                                        if( record.startsWith("//") ) continue; //! ignore comments
					if( record.startsWith("*") ) continue;

					Rational[] ver = new Rational[c-1];

                                        String[] tripData = record.split(" ");

					done++;
					if( done >= 11 ) System.exit(0);

					System.out.println("* --------------------------------------------------");
					System.out.println("* This vertex had "+tripData.length+" co-ordinates.");

					for( int x=1; x<c; x++ )
						{
						String numerator = null;
						String denominator = null;

						String ratString = tripData[x-1];

						int locbar = ratString.indexOf('/');
						if( locbar == -1 )
							{
							numerator = ratString;
							denominator = "1";
							}
						else
							{
							numerator = ratString.substring( 0, locbar );
							denominator = ratString.substring( locbar+1 );
							}

						// System.out.println("* Got rational ["+numerator+"]["+denominator+"] in vertex");

						BigInteger bnum = new BigInteger(numerator);
						BigInteger dnum = new BigInteger(denominator);

						ver[x-1] = new Rational(bnum, dnum);

						}

					Vector<Rational> vec = new Vector<Rational>(ver);

					System.out.println("* Formal vector 'v' has length "+vec.length()+", these are the values:");
					if(DEBUG)
					{
					for( int x=1; x<=vec.length(); x++ )
						{
						if(DEBUG) System.out.println(vec.getEntry(x).toString());
						}
					}
					System.out.println("* Computing Av ");

					Vector<Rational> solution = null;

					solution = a.multiply(vec);
				
					boolean isTight[] = new boolean[r];
					
					int tightIneq = 0;

					for( int x=1; x<=solution.length(); x++ )
						{
						Rational p = solution.getEntry(x);
						Rational q = bvec.getEntry(x);

						int comparison = p.compareTo(q);

						String analysis = "";
						if( comparison == -1 )
							{
							analysis = "VIOLATED";
							System.out.println("* IMPORTANT: This 'vertex' was not even in the polytope!");
							System.out.println("* This is a FAKE VERTEX");
							continue verloop;
							}
						if( comparison == 0 )
							{
							analysis = "TIGHT";
							isTight[x-1] = true;
							tightIneq++;
							}
						if( comparison == 1 )
							{
							analysis = "LOOSE";
							isTight[x-1] = false;
							}

						if(DEBUG) System.out.println("* "+p.toString()+" (b element was: "+q.toString()+") : "+analysis);
						}
					
					System.out.println("* So "+tightIneq+" of the inequalities were tight. Checking the rank of this set...");	

					Rational subnum[][] = new Rational[tightIneq][c];

					int exat = 0;

					for( int scan=0; scan<r; scan++ )
						{
						if( isTight[scan] )
							{
							for( int l=0; l<c; l++ )
								{
								subnum[exat][l] = nums[scan][l];
								}
							exat++;
							}
						}

					System.out.println("* So I just moved "+exat+" rows of the [A;b] matrix to a new formal matrix...");

					Matrix<Rational> submatrix = new Matrix(subnum);

					System.out.println("* Formal submatrix has "+submatrix.getRows()+" rows and "+submatrix.getCols()+" columns.");

					int myrank = submatrix.rank();
					System.out.println("* The submatrix has rank "+myrank);

					if( myrank == c-1 ) System.out.println("* This is a REAL VERTEX");
					else System.out.println("* This is a FAKE VERTEX");
					// System.out.println();
					}

                                }
                        catch (IOException e)
                                {
                                // catch possible io errors from readLine()
                                System.out.println("Problem reading file "+fileName);
                                System.exit(0);
                                }




	}
}

